package com.oneguy.controller; /**
 * Created by ZuoShu on 16/12/4.
 */

import com.oneguy.Cache;
import com.oneguy.Constants;
import com.oneguy.Log;
import com.oneguy.Query;
import com.oneguy.control.MessageHelper;
import com.oneguy.control.message.MessageHandler;
import com.oneguy.control.queue.Handler;
import com.oneguy.control.queue.Message;
import com.oneguy.control.timer.TaskManager;
import com.oneguy.control.util.JaxbUtil;
import com.oneguy.control.util.SignUtil;
import com.oneguy.model.QueryUtil;
import com.oneguy.model.WeixinMessage;
import com.oneguy.model.bean.FishTodaySum;
import com.oneguy.model.bean.RoomInfoEntity;
import com.oneguy.model.service.DailyDataService;
import com.oneguy.model.service.FishService;
import com.oneguy.model.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Controller
public class WeixinController {

    private static final String TAG = "WeiXinController";

    @Autowired
    Environment ev;

    @Autowired
    FishService fishService;

    @Autowired
    DailyDataService dailyDataService;

    @Autowired
    UserService userService;

    private MessageHandler messageHandler;

    private TaskManager taskManager;

    Handler mainHandler;

    private static final int QUERY_FOR_CACHE = 1001;

    private static final int MONITOR_FISH = 1002;

    @Autowired
    public void init() {
        taskManager = new TaskManager();
        taskManager.start();

        messageHandler = new MessageHandler(ev, taskManager);

        Query.getInstance().setFishService(fishService);
        Query.getInstance().setDailyDataService(dailyDataService);
        Query.getInstance().setUserService(userService);

        initHandler();

        addDefaultFishMonitor();
    }

    private void initHandler() {
        mainHandler = new MainHandler();
        mainHandler.sendEmptyMessage(QUERY_FOR_CACHE);
        mainHandler.sendEmptyMessage(MONITOR_FISH);
    }

    private void addDefaultFishMonitor() {
        Map<String, Set<String>> authMap = messageHandler.getTextHandler().getAuthorityMap();
        if (authMap != null && authMap.size() > 0) {
            for (String username : authMap.keySet()) {
                Set<String> auth = authMap.get(username);
                if (auth != null && auth.contains(Constants.C.SZ_FISH_MONITOR)) {
                    Cache.getInstance().addMonitor(Constants.C.SZ_FISH_MONITOR, username);
                    Log.i(TAG, "add default fish monitor:" + username);
                }
            }
        }
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    @ResponseBody
    String home(@RequestParam(value = "signature", required = true) String signature,
                @RequestParam(value = "timestamp", required = true) String timestamp,
                @RequestParam(value = "nonce", required = true) String nonce,
                @RequestParam(value = "echostr", required = true) String echostr) {
        return SignUtil.isValid(signature, timestamp, nonce) ? echostr : "";
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    @ResponseBody
    public String post(HttpServletRequest request, HttpServletResponse response) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        WeixinMessage message = JaxbUtil.fromXml(WeixinMessage.class, sb.toString());
        Log.i(TAG, "receive message:" + message.toString());
        return messageHandler.handleMessage(message);
    }

    @RequestMapping(value = "/room", method = RequestMethod.POST)
    @ResponseBody
    public List<RoomInfoEntity> getRoomSetting(@RequestBody List<RoomInfoEntity> inputRooms) {
        for (RoomInfoEntity room : inputRooms) {
            if (!Cache.getInstance().hasRoom(room)) {
                Cache.getInstance().setRoom(room);
            }
        }
        Cache.getInstance().setLastReadRoomTime(System.currentTimeMillis());
        return Cache.getInstance().getRooms();
    }

    private class MainHandler extends Handler {
        FishTodaySum lastFishTodaySum = null;

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case QUERY_FOR_CACHE:
                    long internal = ev.getProperty("query.internal", Long.class);
//                    Log.i(TAG, "handle QUERY_FOR_CACHE:"+internal);
                    Cache.getInstance().setRevenueScoreList(Query.getInstance().queryRevenue());
                    Cache.getInstance().setActiveUserList(Query.getInstance().queryActiveUser());
                    sendEmptyMessageDelayed(QUERY_FOR_CACHE, internal);
                    break;
                case MONITOR_FISH:
                    queryAndMonitorFish();
                    break;
            }
        }

        private void queryAndMonitorFish() {
            long internal = ev.getProperty("fish.notify.internal", Long.class);
            long count = ev.getProperty("fish.notify.count", Long.class);
            FishTodaySum fishTodaySum = Query.getInstance().queryFishTodaySum();
            if (lastFishTodaySum == null) {
                lastFishTodaySum = fishTodaySum;
                sendEmptyMessageDelayed(MONITOR_FISH, internal);
                return;
            }

            long thisOntable = Long.parseLong(fishTodaySum.getOntable());
            long lastOntable = Long.parseLong(lastFishTodaySum.getOntable());

            long thisWin = Long.parseLong(fishTodaySum.getWin());
            long lastWin = Long.parseLong(lastFishTodaySum.getWin());
            if (Math.abs(thisOntable - lastOntable) >= count
                    || Math.abs(thisWin - lastWin) >= count) {
                // notify
                Set<String> userSet = Cache.getInstance().getMonitorUser(Constants.C.SZ_FISH_MONITOR);
                String content = "=====捕鱼监测=====\n" + QueryUtil.getFishDataString();
                if (userSet != null && userSet.size() > 0) {
                    for (String username : userSet) {
                        MessageHelper.getInstance().sendMessage(username, content);
                    }
                }
                lastFishTodaySum = fishTodaySum;
            }
            sendEmptyMessageDelayed(MONITOR_FISH, internal);
        }
    }
}
